#ifndef LOGMANAGER_H_
#define LOGMANAGER_H_

#include <vector>
#include <set>
#include <string>
#include <list>
#include <stdlib.h>
#include "status.hxx"


class LogFileWriter;
class DbEnvImpl;
class DataStore;
class LogRecord;


class LogManager {

protected:
	LogFileWriter* m_activeLogFile;
	uint32_t m_bufferSize;
    uint32_t m_capacity;
    uint32_t m_curLogInBuffer;
	DbEnvImpl* m_env;
	uint64_t m_nextScn;

    //used for cuncurrent appending(put/del operations)
    pthread_mutex_t m_mutex;

    //the lock used concurrent access to m_lfwList: sync and creating new log files
    pthread_mutex_t m_mutexList;

    //the log file which is not synced yet
    std::list<LogFileWriter*> m_lfwList;
    bool m_inRecovery;
    uint32_t m_flag;

    //list of log file name in log directory
    std::list<std::string> m_logfiles;

public:
	LogManager(DbEnvImpl& env, uint32_t flag);
	~LogManager();

    virtual DbStatus init();

    //flush active log from buffer to disk
	virtual DbStatus flush();
   
    //the logs going to be synced
    std::set<uint32_t> getLogsTobesynced();

    //mark and flush the header of other logs
    DbStatus writeSyncFlag(std::set<uint32_t>& logv);

	virtual DbStatus addRecord(LogRecord& rec);

    //switch log buffer it it has
    virtual void switchLog();

	//recovery:
	//reapply unsynced log records,  update m_entries field into log file header  and set m_nextScn in memory
	// for the last log file, truncate it to correct size in case the trail is written partially
	virtual DbStatus doRecovery();
	DbStatus recovery(uint32_t logId, const std::string& logPath);
    bool inRecovery() {return m_inRecovery; }

	//order by ID
    DbStatus loadLogFiles();

    uint32_t getFlag() { return m_flag; }

    void lock(){pthread_mutex_lock(&m_mutex);}
    void unlock(){pthread_mutex_unlock(&m_mutex);}
    
protected:

	uint32_t getLastLogId();

	//before switch to a new log file, flush the current log file
	DbStatus nextLogFile(LogFileWriter* & lf);
	uint64_t nextScn();

	bool isvalidLogFileName(const std::string& logName);
    std::string getLogFilePath(const std::string& logName);
    std::string getLogFilePath(uint16_t logID);

	bool canbeApplied(LogRecord& rec);

	//applied the log record
	virtual DbStatus apply(LogRecord& rec);
		
};

class LogFileNameComp {

public:
	bool operator()(const std::string& left, const std::string& right) {
	
		uint16_t logIDLeft = atoi(left.c_str());
		uint16_t logIDRight = atoi(right.c_str());

		return logIDLeft < logIDRight;
	}
};

#endif
